package blackberry.util.field;

import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.Ui;
import net.rim.device.api.ui.component.CheckboxField;

public class DjCheckboxField extends DjPreparedLabelManager {

	private ExtendedCheckboxField _checkbox; 
	
	public DjCheckboxField(DjLabelField itemLabel, DjLabelField infoLabel, boolean checked) {
		this(itemLabel, infoLabel, checked, DEFAULT_WIDTH);
	}

	public DjCheckboxField(DjLabelField itemLabel, DjLabelField infoLabel, boolean checked,
			int width) {
		super(itemLabel, infoLabel, width);
		_checkbox =  new ExtendedCheckboxField(checked);
		add(_checkbox);
		setLabelWidth();
	}

	/**
	 * Label 필드가 checkBox 이전에 줄바꿈 되야 하므로 setTrimLabel() 을 재호출 했다.
	 */
	private void setLabelWidth() {
		_itemLabel.setTrimLabel(getCheckBoxLeft() - Ui.convertSize(2, Ui.UNITS_pt, Ui.UNITS_px));
		_infoLabel.setTrimLabel(getCheckBoxLeft() - Ui.convertSize(2, Ui.UNITS_pt, Ui.UNITS_px));
	}
	
	private int getCheckBoxLeft() {
		return getPreferredWidth() - _checkbox.getPreferredWidth();
	}
	
	/**
	 * @원리 height = padding + itemLabel.height + padding + infoLable.height + padding(총3개)
	 * 		 (label.height 는 실제 크기를 이용하기위해 getHeight()를 사용하였다.)
	 */
	public int getPreferredHeight() {
		return _itemLabel.getHeight() + _infoLabel.getHeight() + (DjFieldInfo.DEFAULT_PADDING_SIZE_px * 3);
	}
	
	protected void sublayout(int maxWidth, int maxHeight) {
		
		setPositionChild(_itemLabel, 
				0, 
				DjFieldInfo.DEFAULT_PADDING_SIZE_px);
		layoutChild(_itemLabel, 
				getPreferredWidthOfChild(_itemLabel), 
				getPreferredHeightOfChild(_itemLabel));
	
		setPositionChild(_infoLabel, 
				0, 
				_itemLabel.getTop() + getPreferredHeightOfChild(_itemLabel) + 
						DjFieldInfo.DEFAULT_PADDING_SIZE_px);
		layoutChild(_infoLabel, 
				getPreferredWidthOfChild(_infoLabel), 
				getPreferredHeightOfChild(_infoLabel));
		
		setPositionChild(_checkbox, 
				getCheckBoxLeft(), 
				((getPreferredHeight() - _checkbox.getPreferredHeight()) / 2) - 2/*중심을 맞추기위해*/);
		layoutChild(_checkbox, 
				_checkbox.getPreferredWidth(), 
				_checkbox.getPreferredHeight());
		
		setExtent(getPreferredWidth(), getPreferredHeight());
	}
	
	/**
	 * @재정의_이유
	 *  checkBox 는 너무 작기 때문에 manager 에서 클릭을 해도 변경이 되는 기능이 필요했다.
	 *
	 * checkBox 가 기본적으로 가지고 있는 touchEvent() 메서드와 병행해서 사용하게 되면
	 * 터치가 중복되는 등의 복잡한 문제에 직면하게 된다. 
	 * 따라서 super.touchEvent()를 사용하지 않고 직접 setChecked() 를 사용 하도록 했다.
	 * 
	 */
	protected boolean touchEvent(TouchEvent message) {
		if (message.getEvent() == TouchEvent.DOWN) {
			setFocus();
		}
		if (message.getEvent() == TouchEvent.CLICK) { 
			invokeAction(ACTION_INVOKE);
		}
		return false;//true 는 아무 반응도 하지 못함
	}
	
	/**
	 * checkBox의 대리 메서드들
	 */
	public void setChangeListener(FieldChangeListener listener) {
		_checkbox.setChangeListener(listener);
	}
	
	public void setChecked(boolean checked) {
		_checkbox.setChecked(checked);
	}

	public boolean getChecked() {
		return _checkbox.getChecked();
	}
	
	/**
	 * 크기가 확장된 CheckBoxField 클래스
	 */
	class ExtendedCheckboxField extends CheckboxField {

		/**
		 * label 매개변수로 ""을 입력하면 getPreferredWidth()의 값이 안정적이지 못함.
		 * null 또는 " " 을 입력할것
		 */
		public ExtendedCheckboxField(boolean checked) {
			super(" ", checked);
		}
		
		/**
		 * 기본 포커스가 그려지는걸 막음
		 */
		protected void drawFocus(Graphics graphics, boolean on) {
		}
		
		/**
		 * 자체적인 touch 기능을 수행하지 못하도록 함
		 */
		protected boolean touchEvent(TouchEvent message) {
			return false;
		}
		
		protected boolean invokeAction(int action) {
			return super.invokeAction(action);
		}
	}
}


